using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace Coriander.Xmpp.Logging.Specialized
{
    /// <summary>
    /// 
    /// </summary>
    public class FileLogger : ILogger, IDisposable
    {
        #region * Fields, properties and ctors *

        String filename;
        TextWriterTraceListener listener = null;
        Boolean disposed = false;

        FileMode fileMode = FileMode.Create;

        Int32 sizeLimit;

        Boolean enforceSizeLimit = false;

        /// <summary>
        /// 
        /// </summary>
        public Boolean EnforceSizeLimit
        {
            get { return enforceSizeLimit; }
            set { enforceSizeLimit = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public Int32 SizeLimit
        {
            get { return sizeLimit; }
            set { sizeLimit = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public FileMode FileMode
        {
            get { return fileMode; }
            set { fileMode = value; }
        }

        /// <summary>
        /// Gets the file that's written to
        /// </summary>
        public String Filename
        {
            get { return filename; }
        }

        /// <summary>
        /// ctor
        /// </summary>
        FileLogger() : this(null, FileMode.Create) { }

        /// <summary>
        /// ctor : String, FileMode
        /// </summary>
        /// <param name="filename"></param>
        public FileLogger(String filename, FileMode fileMode)
        {
            this.filename = filename;
            this.fileMode = fileMode;
        }

        # endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        void EnsureFile()
        {
            if (String.IsNullOrEmpty(Filename))
                throw new ArgumentException("filename");

            if (false == Directory.Exists(Path.GetDirectoryName(Filename)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(Filename)); 
            }
            
            if (EnforceSizeLimit)
            {
                FileInfo info = new FileInfo(Filename);

                if (info.Exists && info.Length > SizeLimit)
                {
                    info.Delete(); 
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Open() 
        {
            if (null == listener)
            {
                AddListener(); 
            }
        }

        /// <summary>
        /// 
        /// </summary>
        void AddListener() 
        {
            Trace.AutoFlush = true;

            if (Filename != null)
            {
                EnsureFile();

                Trace.Listeners.Add(
                    listener = new TextWriterTraceListener(
                        File.Open(Filename, FileMode)
                    )
                ); 
            }
        }

        #region ILogger Members

        /// <summary>
        /// 
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        public void Write(string format, params object[] args)
        {
            Trace.WriteLine(
                args.Length > 0 ?
                String.Format(format, args) : format
            );
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// 
        /// </summary>
        /// <param name="disposing"></param>
        void Dispose(Boolean disposing)
        {
            if (false == disposed)
            {
                if (disposing)
                {
                    if (listener != null)
                    {
                        listener.Dispose(); 
                    }
                }

                disposed = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
